package compilers.AST.statement;

import compilers.AST.Node;
import compilers.compiler.PGenerator;
import compilers.exceptions.SemanticalException;
import compilers.symbolTable.SymbolTableScope;

public class BranchStatement extends Statement {
	
	public final static int BREAK = 1;
	public final static int CONTINUE = 2;
	
	private int fType;

	public BranchStatement(int type) {
		fType = type;
	}
	
	public BranchStatement(int type, int lineNr) {
		super(lineNr);
		fType = type;
	}
	
	public void print(int identLevel) {
		println(identLevel, "BranchStatement");
		String typeName = "";
		switch(fType) {
			case BREAK:
				typeName = "break";
				break;
			case CONTINUE:
				typeName = "continue";
				break;
		}
		println(identLevel+1, "Type = " + typeName);
	}

	public void checkSemantics(SymbolTableScope currentScope) throws SemanticalException {
		boolean loopFound = false;
		SymbolTableScope tmpScope = currentScope;
		Node scopeNode = tmpScope.getScopeNode();
		while(scopeNode != null) {
			if(scopeNode instanceof LoopStatement) {
				loopFound = true;
			}
			tmpScope = tmpScope.getParent();
			scopeNode = tmpScope.getScopeNode();
		}
		if(!loopFound) {
			switch(fType) {
				case BREAK:
					throw new SemanticalException("Break-statement not allowed in this context.", getLine());
				case CONTINUE:
					throw new SemanticalException("Continue-statement not allowed in this context.", getLine());
			}
		}
	}
	
	public void generatePcode(PGenerator pGen, SymbolTableScope currentScope) {
		SymbolTableScope tmpScope = currentScope;
		Node loopNode = tmpScope.getScopeNode();
		while(loopNode != null) {
			if(loopNode instanceof LoopStatement) {
				break;
			}
			tmpScope = tmpScope.getParent();
			loopNode = tmpScope.getScopeNode();
		}
		if(fType == BREAK) {
			pGen.unconditionalJump("end_WHILE_" + loopNode.getNodeId());
		} else {
			pGen.unconditionalJump("begin_WHILE_" + loopNode.getNodeId());
		}
	}
}
